
package com.zjff.myshop.front.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.zjff.myshop.entity.User;
import com.zjff.myshop.exception.BusinessException;
import com.zjff.myshop.front.pojo.form.*;
import com.zjff.myshop.front.pojo.vo.UserLoginVO;
import com.zjff.myshop.front.pojo.vo.UserRegisterVO;
import com.zjff.myshop.front.pojo.vo.UserVO;
import com.zjff.myshop.front.service.UserService;
import com.zjff.myshop.util.BeanUtils;
import com.zjff.myshop.util.MD5Util;
import com.zjff.myshop.util.Result;
import io.swagger.annotations.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;

@CrossOrigin
@Api(tags = "02.用户模块",position = 1)
@RestController
@RequestMapping("/app/v1/user")
public class UserController {
    private static final Logger logger = LoggerFactory.getLogger(UserController.class);
    @Resource
    private UserService userService;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 用户登录
     */
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "用户登录", notes = "返回用户id、token")
    @ApiImplicitParam(name = "form", value = "用户登录参数", dataType = "LoginForm", required = true)

    @ApiResponses({
            @ApiResponse(code = 0,message = "成功",response = UserLoginVO.class),
            @ApiResponse(code = 500,message = "失败")
    })

    @PostMapping("/login")
    public Result<UserLoginVO> login(@RequestBody @Valid LoginForm form) {
        User user = userService.login(form.getName(), form.getPassword());
        Integer userId = user.getId();
        //客户端注册用户登录
        StpUtil.login(userId, "Mobile");
        String token = StpUtil.getTokenValue();

        UserLoginVO userLoginVO = new UserLoginVO();
        BeanUtils.copyProperties(user, userLoginVO);
        userLoginVO.setToken(token);
        return Result.ok(userLoginVO);
    }

    /**
     * 用户登录,根据手机号+验证码  By Phone SmsCode
     */
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "用户登录By手机号+验证码", notes = "返回用户id、token")
    @ApiImplicitParam(name = "form", value = "用户登录参数", dataType = "LoginByPhoneForm", required = true)
    @PostMapping("/loginByPhone")
    public Result<UserLoginVO> login(@RequestBody @Valid LoginByPhoneForm form) {
        String phone = form.getPhone();
        User user = userService.selectByPhone(phone);// login(form.getName(), form.getPassword());
        //手机号没注册（对应用户不存在）
        if (ObjectUtil.isNull(user)) {
            throw new BusinessException("手机号没注册");
        }

        //验证码是否还有效
        String code = redisTemplate.opsForValue().get(phone);
        if (!StrUtil.equals(code, form.getCode())) {
            throw new BusinessException("短信验证码无效");
        }

        Integer userId = user.getId();
        //客户端注册用户登录
        StpUtil.login(userId, "Mobile");
        String token = StpUtil.getTokenValue();

        UserLoginVO userLoginVO = new UserLoginVO();
        BeanUtils.copyProperties(user, userLoginVO);
        userLoginVO.setToken(token);
        return Result.ok(userLoginVO);
    }


    /**
     * 用户登出
     */
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "用户登出", notes = "清除token")
    @SaCheckLogin
    @PostMapping("/logout")
    public Result logout() {
        StpUtil.logout();
        return Result.ok(); //登出成功
    }

    /**
     * 用户注册
     */
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "用户注册")
    @ApiImplicitParam(name = "form", value = "用户注册参数", dataType = "UserRegisterForm", required = true)
    @PostMapping("/register")
    public Result<UserRegisterVO> register(@RequestBody @Valid UserRegisterForm form) {

        String password = form.getPassword();
        //用户名已存在
        if (userService.selectByName(form.getName()) != null) {
            throw new BusinessException("用户名已存在");
        }
        User user = new User();
        BeanUtils.copyProperties(form, user);

        //作为练习备用，备注里存放了密码
        user.setRemark(password);
        String salt = MD5Util.md5Encode(String.valueOf(System.currentTimeMillis()), "UTF-8");
        String passwordMd5 = MD5Util.md5Encode(password + salt, "UTF-8");
        user.setSalt(salt);
        user.setPassword(passwordMd5);
        if (userService.insert(user)) {
            logger.info("用户[" + user.getId() + "]注册成功");
            UserRegisterVO userRegisterVO = new UserRegisterVO();
            BeanUtils.copyProperties(user, userRegisterVO);
            return Result.ok(userRegisterVO);
        }
        return Result.error();
    }

    /**
     * 更改用户信息
     */
    @ApiOperationSupport(order = 30)
    @ApiOperation(value = "更改用户信息", notes = "用户id不能为空")
    @ApiImplicitParam(name = "form", value = "用户更改参数", dataType = "UserUpdateForm", required = true)
    @SaCheckLogin
    @PostMapping("/update")
    public Result update(@RequestBody @Valid UserUpdateForm form) {
        int userId = StpUtil.getLoginIdAsInt();
        //如果不是登录用户数据，则抛出异常
        if (userId != form.getId()) {
            throw new BusinessException("业务数据不是你的，禁止该操作！");
        }

        User user = userService.selectByPrimaryKey(userId);
        if (user == null) {
            throw new BusinessException("id对应用户不存在");
        }

        //这里时不能更改密码的
        form.setPassword(null);

        User userForUpdate = new User();
        BeanUtils.copyProperties(form, userForUpdate);

        if (userService.update(userForUpdate)) {//返回成功
            return Result.ok();
        } else { //返回失败
            return Result.error();
        }
    }

    /**
     * 更改用户密码
     */
    @ApiOperationSupport(order = 32)
    @ApiOperation(value = "更改用户密码", notes = "用户id，新旧密码不能为空")
    @ApiImplicitParam(name = "form", value = "用户更改密码参数", dataType = "UserUpdatePwdForm", required = true)
    @SaCheckLogin
    @PostMapping("/updatePwd")
    public Result updatePwd(@RequestBody @Valid UserUpdatePwdForm form) {
        int userId = StpUtil.getLoginIdAsInt();
        //如果不是登录用户数据，则抛出异常
        if (userId != form.getId()) {
            throw new BusinessException("业务数据不是你的，禁止该操作！");
        }

        User user = userService.selectByPrimaryKey(userId);
        if (user == null) {
            throw new BusinessException("id对应用户不存在");
        }

        //若密码不为空字符，则表明用户打算更改密码
        String passwordOld = form.getPasswordOld();
        String passwordOldMd5 = MD5Util.md5Encode(passwordOld + user.getSalt(), "UTF-8");
        if (!StrUtil.equals(passwordOld, passwordOldMd5)) {
            throw new BusinessException("用户原密码错误");
        }

        String passwordNew = form.getPasswordNew();
        String passwordMd5 = MD5Util.md5Encode(passwordNew + user.getSalt(), "UTF-8");

        User userForUpdate = new User();
        userForUpdate.setId(userId);
        userForUpdate.setPassword(passwordMd5);

        if (userService.update(userForUpdate)) {
            return Result.ok();
        } else {
            return Result.error();
        }
    }


    /**
     * 查询我的详情
     */
    @ApiOperationSupport(order = 40)
    @ApiOperation(value = "查询我的详情", notes = "查询当前登录用户的详情信息")
    @SaCheckLogin
    @GetMapping("/getMyDetail")
    public Result<UserVO> getMyDetail() {
        Integer userId = StpUtil.getLoginIdAsInt();
        User user = userService.selectByPrimaryKey(userId);
        if (user == null) {
            throw new BusinessException("id对应用户不存在");
        }
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return Result.ok(userVO);
    }
}
